package com.librariy.view;
import android.app.ProgressDialog;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Region;
import android.hardware.Camera;
import android.os.AsyncTask;
import android.os.Build;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.Toast;
import java.io.ByteArrayOutputStream;
@SuppressWarnings({"deprecation","StaticFieldLeak"})
public class ClipCameraView extends FrameLayout implements SurfaceHolder.Callback{
    private static final String TAG = "ScanCameraView";
    private CameraWrap mCameraWrap=new CameraWrap();
    private float targetAspectRatio = 1.5f;
    private int cameraId=CameraWrap.CAMERA_FACING_BACK;
    private RectF clipRect = new RectF(0, 0, 0, 0);
    private RectF viewRect = new RectF(0, 0, 0, 0);
    private EventListener mListener;
    private SurfaceView mSurfaceView;
    public ClipCameraView(Context mContext) {
        super(mContext);
        this.initialize(mContext);
    }
    public ClipCameraView(Context mContext, AttributeSet attrs) {
        super(mContext, attrs, 0);
        this.initialize(mContext);
    }
    public ClipCameraView(Context mContext, AttributeSet attrs, int defStyleAttr) {
        super(mContext, attrs, defStyleAttr);
        this.initialize(mContext);
    }
    private void initialize(Context mContext) {
        this.mSurfaceView=new SurfaceView(mContext);
        this.mSurfaceView.getHolder().setKeepScreenOn(true);
        this.mSurfaceView.getHolder().addCallback(this);
        super.addView(mSurfaceView,new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
        super.addView(new Sharp(mContext),new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
    }
    public void startPreview() {
        mCameraWrap.initCameraParameters(getDisplay());
        mCameraWrap.startPreview(true);
    }
    public void stopPreview() {
        mCameraWrap.stopPreview(true);
    }
    public void takePicture(final float degrees) {
        mCameraWrap.takePicture(true,new Camera.PictureCallback(){
            @Override
            public void onPictureTaken(byte[] data, Camera camera) {
                stopPreview();
                processImage(data,degrees);
            }
        });
    }
    public void processImage(final byte[] jpeg,final float degrees){
        AsyncTask<Void,Void, byte[]> task=new AsyncTask<Void,Void,byte[]>(){
            private ProgressDialog progressDialog;
            @Override
            protected void onPreExecute() {
                super.onPreExecute();
                progressDialog = ProgressDialog.show(getContext(),"","正在处理图片...");
                mCameraWrap.stopPreview(false);
            }
            @Override
            protected byte[] doInBackground(Void... voids) {
                try {
                    if(clipRect.isEmpty()||viewRect.isEmpty()){
                        return null;
                    }
                    Bitmap srcBitmap= BitmapFactory.decodeByteArray(jpeg,0,jpeg.length);
                    Matrix matrix=new Matrix();
                    //计算图片上的剪裁区域
                    matrix.postScale(srcBitmap.getWidth()/viewRect.width(),srcBitmap.getHeight()/viewRect.height());
                    RectF imgRegion=new RectF(0,0,0,0);
                    matrix.mapRect(imgRegion,clipRect);
                    //剪裁区域缩放
                    matrix.reset();
                    matrix.postScale(clipRect.width()/imgRegion.width(),clipRect.height()/imgRegion.height());
                    matrix.postRotate(degrees);
                    Bitmap newBitmap=Bitmap.createBitmap(srcBitmap,(int)imgRegion.left,(int)imgRegion.top,(int)imgRegion.width(),(int)imgRegion.height(),matrix,false);
                    srcBitmap.recycle();
                    ByteArrayOutputStream out = new ByteArrayOutputStream();
                    newBitmap.compress(Bitmap.CompressFormat.JPEG,80,out);
                    newBitmap.recycle();
                    out.close();
                    return out.toByteArray();
                } catch (Exception e) {
                    Log.e(TAG,"保存文件失败",e);
                    return null;
                }
            }
            @Override
            protected void onPostExecute(byte[] jpeg) {
                super.onPostExecute(jpeg);
                this.progressDialog.dismiss();
                if(jpeg==null){
                    mCameraWrap.startPreview(false);
                    Toast.makeText(getContext(), "拍照失败", Toast.LENGTH_LONG).show();
                    startPreview();
                    return;
                }
                if (mListener != null) {
                    mListener.onFaceCaptured(jpeg);
                }
            }
        };
        task.execute();
    }
    /**
     * 功能一：SurfaceView初始化及回调
     * */
    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        try {
            mCameraWrap.open(getContext(),cameraId);
            mCameraWrap.setPreviewDisplay(holder);
            mCameraWrap.setAdapterSize(holder.getSurfaceFrame());
            startPreview();
            Log.i(TAG,"surfaceCreated=>"+holder.getSurfaceFrame());
        } catch (Exception e) {
            Log.e(TAG,"surfaceCreated Error",e);
            Toast.makeText(getContext(), "摄像头初始化失败！", Toast.LENGTH_LONG).show();
        }
    }
    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        try {
            stopPreview();
            mCameraWrap.setAdapterSize(holder.getSurfaceFrame());
            startPreview();
            Log.i(TAG,"surfaceChanged=>"+holder.getSurfaceFrame());
        } catch (Exception e) {
            Log.e(TAG,"surfaceChanged Error",e);
        }
    }
    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        try {
            Log.i(TAG,"surfaceDestroyed=>"+holder.getSurfaceFrame());
            stopPreview();
            mCameraWrap.release();
        } catch (Exception e) {
            Log.e(TAG,"surfaceDestroyed Error",e);
        }
    }
    /**
     * 功能二：监听器-返回调用者所拍摄的图片
     * */
    public ClipCameraView setEventListener(ClipCameraView.EventListener mListener) {
        this.mListener = mListener;
        return this;
    }
    public interface EventListener {
        void onFaceCaptured(byte[] jpeg);
    }
    /**
     * 功能三：UI显示效果-遮罩
     * */
    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        viewRect.set(0,0,getWidth(),getHeight());
        float min = Math.min(viewRect.width(), viewRect.height()) * 0.8f;
        float max = Math.max(viewRect.width(), viewRect.height()) * 0.8f;
        if (min * targetAspectRatio < max) {
            max = min * targetAspectRatio;
        } else {
            min = max / targetAspectRatio;
        }
        if (viewRect.width() > viewRect.height()) {
            clipRect.set(0, 0, max, min);
        } else {
            clipRect.set(0, 0, min, max);
        }
        clipRect.offsetTo(viewRect.centerX() - clipRect.width() / 2, viewRect.centerY() - clipRect.height() / 2);
    }
    public class Sharp extends View{
        private final float density;
        private final Paint mPaintBg = new Paint(Paint.ANTI_ALIAS_FLAG);
        private final Paint mPaintLine = new Paint(Paint.ANTI_ALIAS_FLAG);
        private final Paint mPaintCorner = new Paint(Paint.ANTI_ALIAS_FLAG);
        public Sharp(Context context) {
            super(context);
            super.setPadding(0, 0, 0, 0);
            this.density = getResources().getDisplayMetrics().density;
            //背景
            mPaintBg.setStyle(Paint.Style.FILL);
            mPaintBg.setColor(0x66000000);
            //边框线
            mPaintLine.setStyle(Paint.Style.STROKE);
            mPaintLine.setStrokeWidth(1);
            mPaintLine.setColor(0xFFFFFFFF);
            //四角
            mPaintCorner.setStyle(Paint.Style.STROKE);
            mPaintCorner.setStrokeWidth((3 * density));
            mPaintCorner.setColor(0xFF59D4D1);
            if(Build.VERSION.SDK_INT>=18){
                return;
            }
            super.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
        }
        @Override
        protected void onDraw(Canvas canvas) {
            //绘制背景
            canvas.clipRect(clipRect,Region.Op.DIFFERENCE);
            canvas.drawColor(0x80000000);
            //绘制边框线
            canvas.clipRect(clipRect,Region.Op.UNION);
            canvas.drawRect(clipRect, mPaintLine);
            //绘制四个角
            float lineLength = density * 40;
            float offset=mPaintCorner.getStrokeWidth()/2;
            //right + top
            canvas.drawLine(clipRect.left, clipRect.top+offset, clipRect.left + lineLength, clipRect.top+offset, mPaintCorner);
            canvas.drawLine(clipRect.left+offset, clipRect.top, clipRect.left+offset, clipRect.top + lineLength, mPaintCorner);
            //right + top
            canvas.drawLine(clipRect.right, clipRect.top+offset, clipRect.right - lineLength, clipRect.top+offset, mPaintCorner);
            canvas.drawLine(clipRect.right-offset, clipRect.top, clipRect.right-offset, clipRect.top + lineLength, mPaintCorner);
            //left + bottom
            canvas.drawLine(clipRect.left, clipRect.bottom-offset, clipRect.left + lineLength, clipRect.bottom-offset, mPaintCorner);
            canvas.drawLine(clipRect.left+offset, clipRect.bottom, clipRect.left+offset, clipRect.bottom - lineLength, mPaintCorner);
            //right + bottom
            canvas.drawLine(clipRect.right, clipRect.bottom-offset, clipRect.right - lineLength, clipRect.bottom-offset, mPaintCorner);
            canvas.drawLine(clipRect.right-offset, clipRect.bottom, clipRect.right-offset, clipRect.bottom - lineLength, mPaintCorner);
        }
    }
}